package routers

import (
	"net/http"
	"strconv"
	"sync"
	"time"

	"law-api-master/log"
)

//KeyResponse return response status about key request
type KeyResponse struct {
	Code int      `json:"code"`
	Msg  string   `json:"msg"`
	Data *KeyData `json:"data"`
}

func newKeyResponse(err error) *KeyResponse {
	code := checkAddErrCode(err)
	msg := "成功"
	if code != 0 {
		msg = err.Error()
	}

	return &KeyResponse{
		Code: code,
		Msg:  msg,
	}
}

//KeyData return response data about key request
type KeyData struct {
	//UserID    string `json:"user_id"`
	Addr      string `json:"chain_address"`
	PubKey    string `json:"public_key"`
	Privkey   string `json:"private_key"`
	Timestamp string `json:"create_time"`
}

func newKeyData(addr, pub, priv, t string) *KeyData {
	return &KeyData{
		Addr:      addr,
		PubKey:    pub,
		Privkey:   priv,
		Timestamp: t,
	}
}

type keyEvent struct {
	Result chan<- *KeyResponse
}

//KeyHandler manager how to deal key request
type KeyHandler struct {
	chain Chain

	reqCh chan *keyEvent

	//key status
	pendingTask    map[string]int
	pendingTaskMux sync.Mutex

	quit chan struct{}
}

//NewKeyHandler is a handler to deal key request
func NewKeyHandler(chain Chain) *KeyHandler {
	kh := &KeyHandler{
		chain: chain,
		reqCh: make(chan *keyEvent),
		quit:  make(chan struct{}),
	}
	go kh.loop()
	return kh
}

//String show the main function of keyhandler
func (kh *KeyHandler) String() string {
	return "generate account from picoChain"
}

//ServeHTTP check and handle key request
func (kh *KeyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		w.Header().Add("Content-Type", "application/json;charset=utf-8")

		//handle key request
		res := make(chan *KeyResponse)
		kh.PostRequestEvent(res)
		respon := <-res

		//response it
		w.Write(encRespon(respon))

	} else {
		log.Warn("unknown request", "method", r.Method)
		w.Write(encRespon(newKeyResponse(ErrHTTPRequest)))
	}

}
func (kh *KeyHandler) Close() {
	close(kh.quit)
}
func (kh *KeyHandler) PostRequestEvent(ch chan<- *KeyResponse) {
	event := &keyEvent{Result: ch}
	//post request event
	select {
	case kh.reqCh <- event:
	case <-kh.quit:
	}

}

//handle different request
func (kh *KeyHandler) loop() {
	for {
		select {
		case event := <-kh.reqCh:
			res := kh.handleKeyRequest()
			event.Result <- res

		case <-kh.quit:
			return
		}
	}

}
func (kh *KeyHandler) handleKeyRequest() *KeyResponse {
	//generate account and permit
	addr, pub, priv, err := kh.chain.GenerateAccount()
	if err != nil {
		log.Warn("handleKeyRequest", "err", err)
		return newKeyResponse(err)
	}

	//pack key data up
	tcreate := strconv.FormatInt(time.Now().Unix(), 10)
	data := newKeyData(addr, pub, priv, tcreate)

	//response
	res := newKeyResponse(nil)
	res.Data = data
	return res
}
